| Path: | vendor/plugins/simply_presentable/README |
| Last Update: | Tue Jan 16 12:25:18 -0800 2007 |
Save keystrokes and stay DRY with SimplyPresentable:
<% present(foo).form do |f| %>
<%= f.text_field :bar %>
<% end %>
Instead of
<% form_for(
foo.new_record? ? {
:url => 'http://example.com/foos',
:html => { :method => 'post', :id => 'new_foo', :class => 'new_foo' }
} :
{
:url => "http://example.com/foos/#{foo.id}",
:html => { :method => 'put', :id => 'foo_1', :class => 'foo' }
} :
) do |f| %>
<%= f.text_field :bar %>
<% end %>
SimplyPresentable is a plugin that introduces the idea of presenters to rails:
martinfowler.com/eaaDev/PresentationModel.html
Rails helpers are functional, and organized around controllers, not domain objects. Helper functions that are intended to operate on data types that span controllers end up being in the ApplicationHelper, or packaged into modules and included in other helpers.
SimplyPresentable attempts to fill the OO void left by a functional helper only approach to presentation:
<%= link_to 'Show Foo', present(@foo).url %>
In this example, the present method (added to ActionController::Base and ActionView::Base) is called on @foo, and instance of a Foo object. When present is called:
Some might consider this a violation of MVC, since the interfaces of the presenters and the domain object are exposed by the presenter proxy. However, MVC is meant to separate IMPLEMENTATION, not interface. You would never want the implementation of a domain model class to depend on the way in which it will be displayed. SimplyPresentable avoids this, by defining all presentation logic in a separate class. The interfaces of the presenter classes and domain models are all exposed through the presenter proxy as a matter of convenience.
script/plugin install svn://richcollins.net/svn/simply_presentable
rake test:plugins
RCOV script/plugin install svn.codahale.com/rails_rcov rake test:plugins:rcov
(SimplyPresentable has also been Heckled)
simply_presentable.richcollins.net/
The presenters included in the plugin are mainly oriented around the ActiveRecord::Base class. There are many instances where information about domain objects is used to control a RESTful rails application. SimplyPresentable is strongly influenced by the idea of convention over configuration. This philosophical choice is apparent in the three core presenters.
SimplyPresentable::ActiveRecordUrlPresenter makes it easy to generate urls based on ActiveRecord::Base instances and named routes. For instance:
routes.rb:
map.resources :foos do |foo|
map.resources :bars
end
in the template / controller:
>> present(bar).url => http://yourdomain.com/foos/1/bars/2
Compare to named url functions:
>> bar_url(:id => bar, :bar_id => bar.foo)
This assumes a few things:
The url helper also includes the methods new_url, edit_url and collection_url.
There are additional options available for name_prefixes, actions and other url customization features. See the documentation for SimplyPresentable::ActiveRecordUrlPresenter.
The SimplyPresentable::ActiveRecordUrlPresenter interface is used by:
SimplyPresentable::ActiveRecordPartialPresenter makes it easier to render partials based on an ActiveRecord::Base instance:
present(Foo.new).render
This will render foos/_new.rhtml
present(Foo.find(:first)).render
This will render foos/_show.rhtml
Compare to render method:
<%= render(:partial => 'foos/' + foo.new_record? ? 'new' : 'show', :locals => { :foo => foo }) %>
You can also change the partial:
present(foo).render(:existing => 'edit')
OR
present(foo).render(:partial => 'edit')
This will render foos/_edit.rhtml
You can also get partial options to be used elsewhere:
present(Foo.find(:first)).partial_options
=> { :partial => 'foos/show', :foo => the_foo_instance }
The SimplyPresentable::ActiveRecordPartialPresenter interface is used by:
SimplyPresentable::ActiveRecordDomPresenter makes it easy to name and control dom and css elements based on an ActiveRecord::Base instance:
present(Foo.new).dom_id => new_foo present(Foo.find(:first)).dom_id => foo_1 present(Foo.find(:first)).dom_class => foo
The SimplyPresentable::ActiveRecordPartialPresenter interface is used by:
SimplyPresentable::ArrayPartialPresenter makes it easier to render partials based on an Array instance:
present(Foo.new, Foo.find(:first)).render_each(:spacer_template => 'foos/between')
This will call render on each Foo instance. The spacer template will be rendered and the results obtained by rendering the Foos will be joined with the spacer template
present(Foo.new, Foo.find(:first)).render_as('foos')
This will render the template foos/index with the array bound to the variable foos.
The plugin expects a directory, RAILS_ROOT/app/presenters that will contain application specific presenters. These presenters will be loaded on each request during development mode. All presenters must inherit from SimplyPresentable::Presenter
You can declare which classes the presenter should be used with:
used_for :foo
This will expose the public methods of the presenter through the PresenterProxy object (or any of its subclasses) that is returned by the present method when a Foo object is passed as an argument.
You can also tell the presenter to skip a class:
not_used_for :bar
This is useful when you have a subclass that should use a different (or no) presenter:
class Foo
end
class Bar < Foo
end
class FooPresenter < SimplyPresentable::Presenter
used_for :foo
not_used_for :bar
end
If there is a "presenter collision", present will throw an Exception:
class FooPresenter < SimplyPresentable::Presenter
used_for :foo
end
class AnotherFooPresenter < SimplyPresentable::Presenter
used_for :foo
end
If presenters share the same inheritance lineage, the sub classes method will be used as expected.
Adam Thorsen helped me extensively with testing and other feedback.
This plugin was inspired by its functional counterpart, simply_helpful:
dev.rubyonrails.org/browser/plugins/simply_helpful
richcollins@gmail.com richcollins.net/